04-데이터베이스연동
데이터베이스 연동 (Tomcat + RDS)
WAS 서버에서 RDS MySQL 데이터베이스에 연결하여 완전한 3-Tier 아키텍처를 완성합니다.
전제조건
- AWS EDU/Archive/조선대학교 AWS 멘토링/Week3-WAS-Deployment/WebWAS분리/01-아키텍처이해및준비 ~ AWS EDU/Archive/조선대학교 AWS 멘토링/Week3-WAS-Deployment/WebWAS분리/03-Web서버연동 완료
- 03-기본실습에서 생성한 RDS 인스턴스 사용 (
webapp-db)
1. MySQL 드라이버 설치
WAS 서버에서 MySQL에 연결하기 위한 드라이버를 설치합니다.
WAS 서버 접속
# Web 서버 → WAS 서버로 접속
ssh -i webapp-keypair.pem ec2-user@[Web서버-Public-IP]
ssh ec2-user@[WAS서버-Private-IP]
MySQL 드라이버 다운로드
# MySQL Connector 다운로드
cd /tmp
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-8.0.33.tar.gz
# 압축 해제
tar -xzf mysql-connector-j-8.0.33.tar.gz
# Tomcat lib 디렉토리로 복사
sudo cp mysql-connector-j-8.0.33/mysql-connector-j-8.0.33.jar /opt/tomcat/lib/
# 소유권 설정
sudo chown tomcat:tomcat /opt/tomcat/lib/mysql-connector-j-8.0.33.jar

2. 환경 변수 설정
DB 연결 정보를 환경 변수로 설정합니다.
RDS 연결 정보 설정
# RDS 연결 정보 환경 변수 설정 (실제 엔드포인트로 교체!)
export DB_HOST="your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"
export DB_USER="admin"
export DB_PASSWORD="webapp123!"
export DB_NAME="webapp_db"
# 영구 설정
echo 'export DB_HOST="your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"' | sudo tee -a /etc/environment
echo 'export DB_USER="admin"' | sudo tee -a /etc/environment
echo 'export DB_PASSWORD="webapp123!"' | sudo tee -a /etc/environment
echo 'export DB_NAME="webapp_db"' | sudo tee -a /etc/environment
# 설정 확인
echo "DB_HOST: $DB_HOST"
echo "DB_USER: $DB_USER"
echo "DB_NAME: $DB_NAME"
DB 연결 테스트
# MySQL 클라이언트 설치 (없는 경우)
sudo yum update -y
sudo yum install mariadb105 -y
# DB 연결 테스트
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME
# 연결되면 다음 명령어로 테스트:
# SHOW TABLES;
# SELECT * FROM users;
# quit
3. 데이터베이스 연동 JSP 페이지 생성
간단한 JSP로 사용자 등록/조회 기능을 만듭니다.
DB 연동 메인 페이지
# 기존 index.jsp를 DB 연동 버전으로 교체
sudo tee /opt/tomcat/webapps/webapp/index.jsp << 'EOF'
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*, java.util.*" %>
<%
// DB 연결 정보
String dbHost = System.getenv("DB_HOST");
String dbUser = System.getenv("DB_USER");
String dbPassword = System.getenv("DB_PASSWORD");
String dbName = System.getenv("DB_NAME");
String dbUrl = "jdbc:mysql://" + dbHost + ":3306/" + dbName;
Connection conn = null;
String message = "";
List<Map<String, String>> users = new ArrayList<>();
try {
// MySQL 드라이버 로드
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
// 사용자 등록 처리
if (request.getMethod().equals("POST")) {
String name = request.getParameter("name");
String email = request.getParameter("email");
if (name != null && email != null && !name.trim().isEmpty() && !email.trim().isEmpty()) {
String insertSql = "INSERT INTO users (name, email) VALUES (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(insertSql);
pstmt.setString(1, name.trim());
pstmt.setString(2, email.trim());
int result = pstmt.executeUpdate();
if (result > 0) {
message = "사용자가 성공적으로 등록되었습니다!";
} else {
message = "등록에 실패했습니다.";
}
pstmt.close();
}
}
// 사용자 목록 조회
String selectSql = "SELECT id, name, email, created_at FROM users ORDER BY created_at DESC";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(selectSql);
while (rs.next()) {
Map<String, String> user = new HashMap<>();
user.put("id", rs.getString("id"));
user.put("name", rs.getString("name"));
user.put("email", rs.getString("email"));
user.put("created_at", rs.getString("created_at"));
users.add(user);
}
rs.close();
stmt.close();
} catch (Exception e) {
message = "데이터베이스 오류: " + e.getMessage();
e.printStackTrace();
} finally {
if (conn != null) {
try { conn.close(); } catch (SQLException e) {}
}
}
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web/WAS/DB 3-Tier 아키텍처</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 900px;
margin: 0 auto;
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
header {
background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
color: white;
padding: 2rem;
text-align: center;
}
header h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
}
main {
padding: 2rem;
}
.section {
margin-bottom: 2rem;
padding: 1.5rem;
background: #f8f9fa;
border-radius: 8px;
border-left: 4px solid #4ECDC4;
}
.form-group {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
}
input[type="text"], input[type="email"] {
width: 100%;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
opacity: 0.9;
}
.message {
padding: 1rem;
background: #d4edda;
color: #155724;
border-radius: 4px;
margin-bottom: 1rem;
}
.user-item {
background: white;
padding: 1rem;
margin-bottom: 0.5rem;
border-radius: 4px;
border-left: 3px solid #4ECDC4;
}
.architecture {
text-align: center;
background: #e3f2fd;
padding: 1rem;
border-radius: 4px;
margin-bottom: 1rem;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1> Web/WAS/DB 3-Tier 아키텍처</h1>
<p>Apache → Tomcat → MySQL RDS</p>
</header>
<main>
<div class="architecture">
<strong>현재 처리 경로:</strong><br>
브라우저 → Apache HTTP Server → Tomcat WAS → RDS MySQL
</div>
<% if (!message.isEmpty()) { %>
<div class="message"><%= message %></div>
<% } %>
<div class="section">
<h2>새 사용자 등록</h2>
<form method="post">
<div class="form-group">
<label for="name">이름:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">이메일:</label>
<input type="email" id="email" name="email" required>
</div>
<button type="submit">등록하기</button>
</form>
</div>
<div class="section">
<h2>등록된 사용자 목록 (<%= users.size() %>명)</h2>
<% if (users.isEmpty()) { %>
<p>등록된 사용자가 없습니다.</p>
<% } else { %>
<% for (Map<String, String> user : users) { %>
<div class="user-item">
<strong><%= user.get("name") %></strong><br>
이메일: <%= user.get("email") %><br>
<small>등록일: <%= user.get("created_at") %></small>
</div>
<% } %>
<% } %>
</div>
</main>
<footer style="background: #333; color: white; text-align: center; padding: 1rem;">
<p>AWS EDU Week2 심화실습 - 완전한 3-Tier 아키텍처</p>
</footer>
</div>
</body>
</html>
EOF
4. Tomcat 재시작
환경 변수와 새로운 코드를 적용하기 위해 Tomcat을 재시작합니다.
서비스 재시작
# Tomcat 재시작
sudo systemctl restart tomcat
# 서비스 상태 확인
sudo systemctl status tomcat
# 로그 확인
sudo tail -f /opt/tomcat/logs/catalina.out
5. 전체 시스템 테스트
완전한 3-Tier 아키텍처를 테스트합니다.
브라우저 테스트
-
Web 서버를 통한 접속:
- URL:
http://[Web서버-Public-IP]/webapp/ - 처리 경로: 브라우저 → Apache → Tomcat → RDS → Tomcat → Apache → 브라우저
- URL:
-
사용자 등록 테스트:
- 이름: 홍길동
- 이메일: hong@example.com
- "등록하기" 버튼 클릭
-
데이터 확인:
- 등록된 사용자가 목록에 표시되는지 확인
- 페이지 새로고침 시 데이터가 유지되는지 확인
명령어 테스트
# Web 서버에서 테스트
curl http://localhost/webapp/
# HTML 응답에 사용자 목록이 포함되어 있으면 성공
데이터베이스 직접 확인
# 실제로 DB에 데이터가 저장되었는지 확인
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME
# MySQL에서 실행:
# SELECT * FROM users ORDER BY created_at DESC LIMIT 5;
# quit
6. 아키텍처 완성도 확인
3-Tier 처리 흐름 검증
-
Presentation Tier (Web): Apache HTTP Server
- 정적 파일 처리
- 프록시 역할
-
Application Tier (WAS): Tomcat
- JSP 처리
- 비즈니스 로직
- DB 연결
-
Data Tier (DB): RDS MySQL
- 데이터 저장/조회
- 트랜잭션 처리
성능 및 확장성
# 동시 처리 테스트 (간단한 부하 테스트)
for i in {1..5}; do
curl -s http://localhost/webapp/ > /dev/null &
done
wait
echo "동시 요청 처리 완료"
완료 체크리스트
아키텍처 완성
최종 시스템 구조
사용자
↓ HTTP 요청
Apache HTTP Server (Public 서브넷)
↓ 프록시 (동적 요청만)
Tomcat WAS (Private 서브넷)
↓ SQL 쿼리
RDS MySQL (Private 서브넷)
↓ 결과
Tomcat WAS
↓ HTML 응답
Apache HTTP Server
↓ HTTP 응답
사용자
분리된 역할
- Apache: 정적 파일 + 프록시
- Tomcat: JSP 처리 + DB 연결
- RDS: 데이터 저장
3-Tier 아키텍처 구축 완료!
Web/WAS/DB가 완전히 분리된 확장 가능하고 안전한 시스템이 완성되었습니다. 이제 각 계층을 독립적으로 확장하거나 관리할 수 있습니다.
7. 트러블슈팅
환경변수 관련 문제
문제: DB 연결 실패 - 환경변수를 읽어오지 못함
# 현재 설정된 환경변수 확인
echo "DB_HOST: $DB_HOST"
echo "DB_USER: $DB_USER"
echo "DB_PASSWORD: $DB_PASSWORD"
echo "DB_NAME: $DB_NAME"
해결방법 1: Tomcat 서비스 파일에 환경변수 직접 추가
# Tomcat systemd 서비스 파일 편집
sudo systemctl edit tomcat
# 다음 내용 추가:
[Service]
Environment="DB_HOST=your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"
Environment="DB_USER=admin"
Environment="DB_PASSWORD=webapp123!"
Environment="DB_NAME=webapp_db"
# 서비스 재시작
sudo systemctl daemon-reload
sudo systemctl restart tomcat
해결방법 2: Tomcat 시작 스크립트에 환경변수 설정
# setenv.sh 파일 생성
sudo tee /opt/tomcat/bin/setenv.sh << 'EOF'
export DB_HOST="your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"
export DB_USER="admin"
export DB_PASSWORD="webapp123!"
export DB_NAME="webapp_db"
EOF
# 실행권한 부여
sudo chmod +x /opt/tomcat/bin/setenv.sh
sudo chown tomcat:tomcat /opt/tomcat/bin/setenv.sh
# Tomcat 재시작
sudo systemctl restart tomcat
문제: 환경변수는 설정되었지만 JSP에서 null 값 반환
# JSP에서 디버깅용 코드 임시 추가
<%
out.println("DB_HOST from env: " + System.getenv("DB_HOST"));
out.println("DB_USER from env: " + System.getenv("DB_USER"));
%>
해결방법: context.xml에 환경변수를 리소스로 등록
# Tomcat context.xml 편집
sudo vi /opt/tomcat/conf/context.xml
# <Context> 태그 안에 추가:
<Environment name="DB_HOST" type="java.lang.String" value="your-rds-endpoint" />
<Environment name="DB_USER" type="java.lang.String" value="admin" />
<Environment name="DB_PASSWORD" type="java.lang.String" value="webapp123!" />
<Environment name="DB_NAME" type="java.lang.String" value="webapp_db" />
# JSP에서 JNDI로 접근:
<%
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
String dbHost = (String)envContext.lookup("DB_HOST");
%>
네트워크 연결 문제
문제: 타임아웃 에러로 RDS 연결 실패
# 네트워크 연결 테스트
telnet $DB_HOST 3306
# 보안그룹 확인 (AWS CLI 필요)
aws ec2 describe-security-groups --group-names rds-security-group
해결방법: 보안그룹 설정 확인 및 수정
- RDS 보안그룹에서 WAS 서버 보안그룹으로부터 포트 3306 허용 확인
- WAS 서버 보안그룹에서 아웃바운드 3306 포트 허용 확인
- 서브넷 라우팅 테이블 확인
MySQL 드라이버 문제
문제: ClassNotFoundException - MySQL 드라이버를 찾을 수 없음
# 드라이버 파일 존재 확인
ls -la /opt/tomcat/lib/mysql-connector-j*.jar
# 파일 권한 확인
stat /opt/tomcat/lib/mysql-connector-j*.jar
해결방법: 드라이버 재설치 및 권한 수정
# 기존 드라이버 삭제 후 재설치
sudo rm -f /opt/tomcat/lib/mysql-connector-j*.jar
# 최신 버전 다운로드
cd /tmp
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-8.2.0.tar.gz
tar -xzf mysql-connector-j-8.2.0.tar.gz
sudo cp mysql-connector-j-8.2.0/mysql-connector-j-8.2.0.jar /opt/tomcat/lib/
# 올바른 권한 설정
sudo chown tomcat:tomcat /opt/tomcat/lib/mysql-connector-j-8.2.0.jar
sudo chmod 644 /opt/tomcat/lib/mysql-connector-j-8.2.0.jar
# Tomcat 재시작
sudo systemctl restart tomcat
메모리 부족 문제
문제: OutOfMemoryError 발생
# 현재 메모리 사용량 확인
free -h
top -p $(pgrep -f tomcat)
해결방법: Tomcat 메모리 설정 조정
# setenv.sh에 메모리 옵션 추가
echo 'export CATALINA_OPTS="-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m"' | sudo tee -a /opt/tomcat/bin/setenv.sh
# Tomcat 재시작
sudo systemctl restart tomcat
관련 문서: AWS EDU/Archive/조선대학교 AWS 멘토링/Week2-Dynamic-WebApp-Deployment/Week2-전체가이드, AWS EDU/Archive/조선대학교 AWS 멘토링/Week3-WAS-Deployment/WebWAS분리/03-Web서버연동